package com.baturu.vin.benz.service.impl;

import com.baturu.vin.benz.dto.BenzEPCPartsInfoDTO;
import com.baturu.vin.benz.dto.BenzFootNoteInfoDTO;
import com.baturu.vin.benz.dto.BenzFootnoteDetailDTO;
import com.baturu.vin.benz.dto.BenzVinInfoDTO;
import com.baturu.vin.benz.service.impl.util.BenzStringUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 奔驰vin码和配件编码解析器
 *
 * @author 蒋鑫磊
 * @Time 2016/11/17.
 */
@Slf4j
@Service("benzDateService")
public class BenzDateService {


    private static final Pattern PATTERN = Pattern.compile("[A-Z]\\s(\\d{14}|\\s{6}\\d{8}|\\d{6})(\\s+\\d{3,})?\\s*");

    @Autowired
    private BenzCarTypeInfoService benzCarTypeInfoService;

    /**
     * 车型日期转换
     *
     * @param productTime 6位日期字符串 yyMMdd
     * @return Date 日期
     */
    public Date buildCarTypeProductTime(String productTime) {
        if (StringUtils.isBlank(productTime) || StringUtils.length(productTime) < 6) {
            return null;
        }
        String yearString = productTime.substring(0, 2);
        int year = Integer.valueOf(yearString);
        String monthString = productTime.substring(2, 4);
        String dayString = productTime.substring(4, 6);
        //如果年份后2位 小于60 ,取20XX, 否则19XX
        if (year < 60) {
            if (year < 10) {
                productTime = "200" + year + "-" + monthString + "-" + dayString;
            } else {
                productTime = "20" + year + "-" + monthString + "-" + dayString;
            }
        } else {
            productTime = "19" + year + "-" + monthString + "-" + dayString;
        }
        Date date = null;
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            date = dateFormat.parse(productTime);
        } catch (ParseException e) {
            log.error(" 奔驰车型生产日期转化出错 : " + productTime);
        }
        return date;
    }

    /**
     * 配件生产日期或截止日期转换
     *
     * @param productTime 8位日期字符串 yyyyMMdd
     * @return Date 日期
     */
    public Date buildPartsProductTime(String productTime) {
        if (StringUtils.isBlank(productTime) || StringUtils.length(productTime) < 8) {
            return null;
        }
        Date date;
        try {
            String yearString = productTime.substring(0, 4);
            int year = Integer.valueOf(yearString);
            String monthString = productTime.substring(4, 6);
            String dayString = productTime.substring(6, 8);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            date = dateFormat.parse(year + "-" + monthString + "-" + dayString);
        } catch (ParseException | NumberFormatException e) {
            log.error(" 奔驰配件生产日期转化出错 : " + productTime);
            return null;
        }
        return date;
    }

    private boolean filterDate(BenzEPCPartsInfoDTO p, Date carProductTime, BenzVinInfoDTO benzVinInfoDTO) {
        String fitchass = BenzStringUtil.buildFitChass(benzVinInfoDTO.getChassIdent());
        String firstStr = fitchass.substring(0, 1);
        String lastStr = fitchass.substring(1);
        int lastStrValue = Integer.parseInt(lastStr);
        if (CollectionUtils.isEmpty(p.getBeginFitChassList()) && CollectionUtils.isEmpty(p.getEndFitChassList())) {
            return filterByProductTime(p, carProductTime);
        }
        //判断不符合年限的(SA)
        if (StringUtils.isNotBlank(p.getNoFitSa())) {
            if (BenzStringUtil.filterNotFitSa(benzVinInfoDTO.getSaCodeSet(), p.getNoFitSa())) {
                return false;
            }
        }
        boolean beginFilter = true;
        boolean endFilter = true;
        if (CollectionUtils.isNotEmpty(p.getBeginFitChassList())) {
            beginFilter = false;
            for (int i = 0; i < p.getBeginFitChassList().size(); i++) {
                String sFitChass = p.getBeginFitChassList().get(i);
                if (StringUtils.isBlank(sFitChass)) {
                    continue;
                }
                if (!sFitChass.startsWith(firstStr)) {
                    continue;
                }
                if (sFitChass.length() == 1) {
                    beginFilter = filterByProductTime(p, carProductTime);
                    continue;
                }
                if (Integer.parseInt(sFitChass.substring(1)) <= lastStrValue) {
                    beginFilter = true;
                    break;
                }
            }
        }
        if (CollectionUtils.isNotEmpty(p.getEndFitChassList())) {
            endFilter = false;
            for (int i = 0; i < p.getEndFitChassList().size(); i++) {
                String endFitChass = p.getEndFitChassList().get(i);
                if (StringUtils.isBlank(endFitChass)) {
                    continue;
                }
                if (!endFitChass.startsWith(firstStr)) {
                    continue;
                }
                if (endFitChass.length() == 1) {
                    endFilter = filterByProductTime(p, carProductTime);
                    continue;
                }
                if (Integer.parseInt(endFitChass.substring(1)) >= lastStrValue) {
                    endFilter = true;
                    break;
                }
            }
        }
        return beginFilter && endFilter;
    }

    private boolean filterByProductTime(BenzEPCPartsInfoDTO p, Date carProductTime) {
        if (carProductTime == null) {
            return true;
        }
        if (p.getBeginProductTime() == null && p.getEndProductTime() == null) {
            return true;
        }
        if (p.getBeginProductTime() == null) {
            return p.getEndProductTime().after(carProductTime);
        }
        if (p.getEndProductTime() == null) {
            return p.getBeginProductTime().before(carProductTime);
        }
        //起始 结束时间都有
        return p.getBeginProductTime().before(carProductTime) && p.getEndProductTime().after(carProductTime);
    }

    private boolean filterColorCodeByProductTime(String linkedFootnotes, BenzVinInfoDTO benzVinInfoDTO, BenzEPCPartsInfoDTO benzEPCPartsInfoDTO) {
        String fitChass = BenzStringUtil.buildFitChass(benzVinInfoDTO.getChassIdent());
        String productTime = benzVinInfoDTO.getDeliveryDate();
        Date carProductTime = null;
        if (StringUtils.isNotBlank(productTime) && productTime.trim().length() == 6) {
            carProductTime = buildCarTypeProductTime(productTime);
        }
        fillColorDate(linkedFootnotes, benzEPCPartsInfoDTO, fitChass);
        //过滤车型日期
        return filterDate(benzEPCPartsInfoDTO, carProductTime, benzVinInfoDTO);
    }

    private void fillColorDate(String linkedFootnotes, BenzEPCPartsInfoDTO benzEPCPartsInfoDTO, String fitChass) {
        List<String> footNoteList = buildColorFootNoteList(linkedFootnotes);
        List<BenzFootNoteInfoDTO> benzFootNoteInfoDTOs = benzCarTypeInfoService.getColorFootNoteInfoDTOs(benzEPCPartsInfoDTO, footNoteList);
        if (CollectionUtils.isEmpty(benzFootNoteInfoDTOs)) {
            return;
        }
        benzEPCPartsInfoDTO.setBeginProductTime(null);
        benzEPCPartsInfoDTO.setEndProductTime(null);
        benzEPCPartsInfoDTO.setBeginFitChassList(Lists.newArrayList());
        benzEPCPartsInfoDTO.setEndFitChassList(Lists.newArrayList());
        benzEPCPartsInfoDTO.setNoFitSa(null);
        Map<String, BenzFootNoteInfoDTO> footNoteInfoDTOMap = benzFootNoteInfoDTOs.stream()
                .collect(Collectors.toMap(p -> p.getCatNum() + "-" + p.getGroupNum() + "-" + p.getFootnote(), p -> p, (p1, p2) -> p2));
        footNoteList.forEach(f -> {
            String footNoteIdentity = benzEPCPartsInfoDTO.getCatNum() + "-" + benzEPCPartsInfoDTO.getGroupNum() + "-" + f;
            BenzFootNoteInfoDTO footNoteInfoDTO = footNoteInfoDTOMap.get(footNoteIdentity);
            fillSingleFootNotePartsProductTime(footNoteInfoDTO, benzEPCPartsInfoDTO, fitChass);
        });
    }

    private void fillSingleFootNotePartsProductTime(BenzFootNoteInfoDTO footNoteInfoDTO, BenzEPCPartsInfoDTO p, String fitChass) {
        if (footNoteInfoDTO == null) {
            return;
        }
        String content = footNoteInfoDTO.getContent();
        if (StringUtils.isBlank(content)) {
            return;
        }

        Matcher matcher = PATTERN.matcher(content);
        if (!matcher.find()) {
            return;
        }
        String[] split = content.split(" ");
        List<String> contentList = Lists.newArrayList(split).stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(contentList)) {
            return;
        }
        String chassStr = contentList.get(0);
        String dateStr = null;
        String noFitSaStr = null;
        if (contentList.get(1).length() == 14) {
            chassStr = chassStr + contentList.get(1).substring(0, 6);
            dateStr = contentList.get(1).substring(6, 14);
        } else if (contentList.get(1).length() == 8) {
            dateStr = contentList.get(1);
        } else {
            chassStr = chassStr + contentList.get(0) + contentList.get(1);
        }
        //只拿匹配的底盘,比如A123456只拿A的不拿LV等其他,否则后续比较繁琐
        if (StringUtils.isNotBlank(chassStr)) {
            if (!chassStr.substring(0, 1).equals(fitChass.substring(0, 1))) {
                return;
            }
        }
        if (contentList.size() > 2) {
            noFitSaStr = contentList.get(2);
        }
        Date date = buildPartsProductTime(dateStr);
        if (date == null) {
            return;
        }
        if (StringUtils.isNotBlank(noFitSaStr) && noFitSaStr.length() != 3) {
            noFitSaStr = "";
        }
        String contentType = footNoteInfoDTO.getContentType();
        if (StringUtils.isBlank(contentType)) {
            return;
        }
        if (contentType.startsWith("#B") || contentType.startsWith("EB")) {
            if (StringUtils.isNotBlank(chassStr)) {
                if (CollectionUtils.isEmpty(p.getEndFitChassList())) {
                    p.setEndFitChassList(new ArrayList<>());
                }
                p.getEndFitChassList().add(chassStr);
            }
            if (p.getEndProductTime() == null) {
                p.setEndProductTime(date);
            } else if (p.getEndProductTime().before(date)) {
                p.setEndProductTime(date);
            }
            if (StringUtils.isBlank(p.getNoFitSa())) {
                p.setNoFitSa(noFitSaStr);
            }
            return;
        }
        if (StringUtils.isNotBlank(chassStr)) {
            if (CollectionUtils.isEmpty(p.getBeginFitChassList())) {
                p.setBeginFitChassList(new ArrayList<>());
            }
            p.getBeginFitChassList().add(chassStr);
        }
        if (p.getBeginProductTime() == null) {
            p.setBeginProductTime(date);
        } else if (p.getBeginProductTime().after(date)) {
            p.setBeginProductTime(date);
        }
        if (StringUtils.isBlank(p.getNoFitSa())) {
            p.setNoFitSa(noFitSaStr);
        }

    }

    private List<String> buildColorFootNoteList(String footnotes) {
        if (StringUtils.isBlank(footnotes)) {
            footnotes = "";
        }
        if (footnotes.length() >= 6 && footnotes.length() < 9) {
            return Lists.newArrayList(footnotes.substring(0, 3), footnotes.substring(3, 6));
        } else if (footnotes.length() >= 9 && footnotes.length() < 12) {
            return Lists.newArrayList(footnotes.substring(0, 3), footnotes.substring(3, 6),
                    footnotes.substring(6, 9));
        } else if (footnotes.length() >= 12) {
            return Lists.newArrayList(footnotes.substring(0, 3), footnotes.substring(3, 6),
                    footnotes.substring(6, 9), footnotes.substring(9, 12));
        } else {
            return Lists.newArrayList(footnotes);
        }
    }

    public String getColorCode(List<BenzFootnoteDetailDTO> benzFootnoteDetailDTOs, BenzEPCPartsInfoDTO benzEPCPartsInfoDTO, BenzVinInfoDTO benzVinInfoDTO) {
        if (CollectionUtils.isEmpty(benzFootnoteDetailDTOs)) {
            return "";
        }
        //单条记录的
        benzFootnoteDetailDTOs.forEach(d -> {
            String content = d.getContent();
            if (StringUtils.isBlank(content)) {
                d.setColorCode("");
                return;
            }
            //反编译那边拿到的方法..呵呵呵,存放数据用位数来的,万一少了个空格不是炸了么
            String saCode = null;
            String linkedFootnotes = null;
            String colorCode = null;
            if (content.length() > 21) {
                saCode = content.substring(21).trim();
            }
            if (content.length() > 5) {
                if (content.length() > 21) {
                    linkedFootnotes = content.substring(5, 21).trim();
                } else {
                    linkedFootnotes = content.substring(5).trim();
                }
            }
            if (content.length() > 0) {
                if (content.length() > 5) {
                    if (!content.substring(0, 5).startsWith(" ")) {
                        colorCode = content.substring(0, 5).trim();
                    }
                } else {
                    colorCode = content.trim();
                }
            }
            if (StringUtils.isNotBlank(colorCode) && colorCode.length() != 4) {
                d.setColorCode("");
                return;
            }
            //检测注脚的 SA是否符合
            if (StringUtils.isNotBlank(saCode)) {
                Optional<String> optional = Lists.newArrayList(saCode.split("/")).stream().filter(c -> BenzStringUtil.checkSingleSAMatch(c, benzVinInfoDTO.getSaCodeSet())).findFirst();
                if (!optional.isPresent()) {
                    d.setColorCode("");
                    return;
                }
            }
            if (StringUtils.isNotBlank(linkedFootnotes)) {
                // 检测注脚的日期是否符合
                if (!filterColorCodeByProductTime(linkedFootnotes, benzVinInfoDTO, benzEPCPartsInfoDTO)) {
                    d.setColorCode("");
                    return;
                }
            }
            //检测色码是不是正常 比如31 0这样的坑货
            if (StringUtils.isBlank(colorCode) || colorCode.contains(" ")) {
                d.setColorCode("");
                return;
            }
            d.setColorCode(colorCode);
        });
        if (benzFootnoteDetailDTOs.size() == 1) {
            return benzFootnoteDetailDTOs.get(0).getColorCode();
        }

        List<BenzFootnoteDetailDTO> colorCodeFootNotes = benzFootnoteDetailDTOs.stream().filter(e -> StringUtils.isNotBlank(e.getColorCode())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(colorCodeFootNotes)) {
            return "";
        }
        return colorCodeFootNotes.get(0).getColorCode();
    }

}
